package com.time.workbench.efficient.util;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.time.workbench.efficient.consts.CmdConst;
import com.time.workbench.efficient.entity.dto.ServerSessionInfo;
import com.time.workbench.release.consts.BuildConfig;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 自动部署攻击类
 */
@Slf4j
public class DeployUtil {

    /**
     * 获取服务器session
     *
     * @return
     */
    @SneakyThrows
    public static Session getSession(String sshHost, int sshPort, String sshUser, String sshPass) {
        Session serverSession = JschUtil.createSession(sshHost, sshPort, sshUser, sshPass);
        serverSession.setTimeout(2000);
        return serverSession;
    }


    /**
     * 连接服务器
     *
     * @param session
     */
    public static void connectServer(Session session) {
        try {
            if (!session.isConnected())
                session.connect();
        } catch (JSchException e) {
            log.info("服务器连接失败,", e);
        }
    }

    /**
     * git 拉取代码
     *
     * @param gitPullBaseDirectory 拉取目录
     * @param projectCode          项目code
     * @param gitRemoteAddress     git地址
     * @param branch               拉取分支
     * @return
     */
    public static List<String> gitPullCodeCmd(String gitPullBaseDirectory, String projectCode, String gitSourceDirect, String gitRemoteAddress, String branch) {
        // 创建目录
        List<String> cmdArray = new ArrayList<>();
        cmdArray.add(StrUtil.format(CmdConst.mkdirP, gitPullBaseDirectory + File.separator + projectCode));


        //git clone
        cmdArray.add(StrUtil.format(CmdConst.gitCloneTemplate, gitRemoteAddress) + " " + gitSourceDirect);

        //git checkout切换指定分支
        cmdArray.add(cdCurrentDirCmd(gitSourceDirect) + StrUtil.format(CmdConst.gitCheckoutTemplate, branch));

        // git pull
        cmdArray.add(cdCurrentDirCmd(gitSourceDirect) + StrUtil.format(CmdConst.gitPullCodeTemplate));

        cmdArray.add("exit");
        return cmdArray;
    }

    /**
     * maven打包组成cmd命令
     *
     * @param currentDir    去哪个目录打包
     * @param packageModule 打包模块
     * @return
     */
    public static List<String> mavenPackageCmd(String currentDir, String packageModule) {
        List<String> cmdArray = new ArrayList<>();
        // 打包
        if (StrUtil.isNotEmpty(packageModule)) {
            packageModule = "-pl " + packageModule;
        }
        cmdArray.add(DeployUtil.cdCurrentDirCmd(currentDir) + StrUtil.format(CmdConst.mvnPackageAm, packageModule));
        cmdArray.add("exit");
        return cmdArray;
    }

    /**
     * maven打包
     *
     * @param gitSourceDirect
     * @param packageModule
     * @param serverSession
     * @return
     */
    public static String mavenPackage(String gitSourceDirect, String packageModule, Session serverSession, String findLastName) {
        List<String> cmdArray = mavenPackageCmd(gitSourceDirect, packageModule);

        JschUtil.execByShell(serverSession, cmdArray, StandardCharsets.UTF_8);

        String jarFileName = getPackageFile(gitSourceDirect, packageModule, serverSession, findLastName);

        return jarFileName.replace("\n", "");
    }

    public static String getPackageFile(String gitSourceDirect, String packageModule, Session session, String findLastName) {

        // 获取打包后的名称
        String jarFileName = JschUtil.exec(session, StrUtil.format
                        (CmdConst.findLastName, gitSourceDirect + File.separator + packageModule + File.separator + "target" + File.separator, findLastName),
                StandardCharsets.UTF_8);
        return jarFileName.replace("\n", "");
    }


    /**
     * 监听pid
     *
     * @param pid
     * @param monitorNumber
     * @param monitorTime
     * @param projectCode
     * @param session
     * @return
     */
    public static boolean monitorPid(String pid, Integer monitorNumber, Integer monitorTime, String projectCode, Session session) {
        for (int i = 0; i < monitorNumber; i++) {
            try {
                if (!pidExist(pid, session)) {
                    log.error(projectCode + "启动失败");
                    return false;
                }
                log.info("{} 监听是否成功:第{}次", projectCode, i + 1);
                Thread.sleep(monitorTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        log.info("{} 启动成功", projectCode);
        return true;
    }

    /**
     * 判断pid是否存在
     *
     * @param pid
     * @param session
     * @return false不存在 true 存在
     */
    public static boolean pidExist(String pid, Session session) {
        return (JschUtil.exec(session, StrUtil.format(CmdConst.findMax1D, File.separator + "proc" + File.separator, pid), StandardCharsets.UTF_8).indexOf("proc") > 0);
    }

    /**
     * 生成未占用的端口
     *
     * @return
     */
    public static Integer newPort(Session session) {
        int port;
        do {
            port = RandomUtil.randomInt(5000, 9000);
        } while (StrUtil.isNotBlank(JschUtil.exec(session, StrUtil.format(CmdConst.lsofPort, port), StandardCharsets.UTF_8)));

        return port;
    }

    public static String cdCurrentDirCmd(String currentDir) {
        return "cd " + currentDir + " && ";
    }

}
